//数码管显示模块
module segment_prj(
    rst_n,
    clk,
    display,
    display_vld,
    seg_sel,
    segment  
);
parameter  SEG_WID        =       8           ;
parameter  SEG_NUM        =       8           ;
parameter  CNT_WID        =       10          ;
parameter  TIME_20US      =       10'd1000    ;
//parameter  TIME_20US      =       50000000    ;
parameter  NUM_0          =       8'b0011_1111;
parameter  NUM_1          =       8'b0000_0110;
parameter  NUM_2          =       8'b0101_1011;
parameter  NUM_3          =       8'b0100_1111;
parameter  NUM_4          =       8'b0110_0110;
parameter  NUM_5          =       8'b0110_1101;
parameter  NUM_6          =       8'b0111_1101;
parameter  NUM_7          =       8'b0000_0111;
parameter  NUM_8          =       8'b0111_1111;
parameter  NUM_9          =       8'b0110_1111;
//parameter  NUM_10         =       8'b1010_0000;
parameter  NUM_ERR        =       8'b0000_0000;

 
integer                           ii          ;
input                             clk         ;//时钟信号
input                             rst_n       ;//复位信号
output [SEG_WID - 1:0]            seg_sel     ;//7段数码管位选信号
output [SEG_WID - 1:0]            segment     ;//7位数码管段选信号
input  [SEG_NUM*4-1:0]            display     ;//显示数据输出信号
input                             display_vld ;//显示数据有效指示信号

reg    [SEG_WID - 1:0]            seg_sel     ;
reg    [SEG_WID - 1:0]            segment     ;
reg    [ 31    :    0]            count_20us  ;
reg    [SEG_NUM - 1:0]            sel_cnt     ;
reg    [ 4 - 1 :    0]            seg_tmp     ;

wire                              add_count_20us  ;
wire                              end_count_20us  ;
wire                              add_sel_cnt ;
wire                              end_sel_cnt ;

wire    [SEG_NUM*4-1:0]           display     ;	
reg     [SEG_NUM*4-1:0]           display_ff0 ;
wire                              display_vld ;	

assign add_count_20us = 1;
assign end_count_20us = add_count_20us  && count_20us == TIME_20US-1;

always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        count_20us <= 0; 
    end
    else if(add_count_20us) begin
       if(end_count_20us)
           count_20us <= 0; 
        else
           count_20us <= count_20us+1;
	end
end

assign add_sel_cnt = end_count_20us;
assign end_sel_cnt = add_sel_cnt  && sel_cnt == SEG_NUM-1;
//计数器
always @(posedge clk or negedge rst_n) begin 
    if (rst_n==1'b0) begin
       sel_cnt <= 0; 
   end
    else if(add_sel_cnt) begin
       if(end_sel_cnt)
           sel_cnt <= 0; 
       else
           sel_cnt <= sel_cnt+1 ;
   end
end

//位选
always  @(posedge clk or negedge rst_n)begin
   if(rst_n==1'b0)begin
       seg_sel <= {SEG_NUM{1'b0}};
   end
  else begin
        seg_sel <= 1'b1 << sel_cnt;
    end
end

always  @(posedge clk or negedge rst_n)begin
   if(rst_n==1'b0)begin
      display_ff0 <= 0;
  end
  else begin
        for(ii=0;ii<SEG_NUM;ii=ii+1)begin
           if(display_vld==1)begin
               display_ff0[(ii+1)*4-1 -:4] <= display[(ii+1)*4-1 -:4];
           end
           else begin
               display_ff0[(ii+1)*4-1 -:4] <= display_ff0[(ii+1)*4-1 -:4];
           end
    end
   end
end

always  @(*)begin
    seg_tmp = display_ff0[(sel_cnt+1)*4-1 -:4]; 
end

//段选
always  @(posedge clk or negedge rst_n)begin
   if(rst_n==1'b0)begin
        segment <= NUM_0;
    end
   else begin
        case(seg_tmp)
            0 :segment <=NUM_0  ; 
            1 :segment <=NUM_1  ; 
            2 :segment <=NUM_2  ; 
            3 :segment <=NUM_3  ; 
            4 :segment <=NUM_4  ; 
            5 :segment <=NUM_5  ; 
            6 :segment <=NUM_6  ; 
            7 :segment <=NUM_7  ; 
            8 :segment <=NUM_8  ; 
            9 :segment <=NUM_9  ; 
            //10:segment <=NUM_10 ;
            default:segment <= NUM_ERR;
      endcase 
    end
end


endmodule
